#include <stdio.h>
#include <string.h>

#include "NUC900_reg.h"
#include "wblib.h"
#include "NUC900_vpost.h"
#include "Inc/ADC.h"

#define printf sysprintf


#define REAL_CHIP 1
#define CACHE_ON 0


#define LEN                  8
#define SHIFT                3

#define AXIS_X1             60
#define AXIS_Y1             60 
#define AXIS_X2            260
#define AXIS_Y2             60   
#define AXIS_X3             60
#define AXIS_Y3            180
#define AXIS_X4            260
#define AXIS_Y4            180


volatile adc_con_union		ADC_CON_REG;
volatile adc_tsc_union		ADC_TSC_REG;
volatile adc_dly_union		ADC_DLY_REG;
volatile adc_xdata_union	ADC_XDATA_REG;
volatile adc_ydata_union    ADC_YDATA_REG;

VOID SetTarget(INT16 Center_X, INT16 Center_Y);
VOID ResetScreen(VOID);

UINT32 volatile pre_x,pre_y;

INT16 AXIS_X[LEN], AXIS_Y[LEN];
INT COUNT;
INT16 OUTPUT_X, OUTPUT_Y;
int volatile IsTouch;
int volatile t;
int volatile LCD_BUFF_BASE;

#if REAL_CHIP
short ADCDataIn()
{

	INT16 X,Y;
	int i;
	
	//X = pre_x; 
	//Y = pre_y;
	
	//1024X1024 => 240X320
	//pre_x=(readw(ADC_XDATA_ADD)*15)>>6;
    //pre_y=((readw(ADC_YDATA_ADD)*5)>>4);	
	
	//1024X1024 => 320X240
	pre_x=(readw(ADC_XDATA_ADD)*5)>>4;
	pre_y=((readw(ADC_YDATA_ADD)*15)>>6);
	
    AXIS_X[COUNT] = pre_x; 
    AXIS_Y[COUNT] = pre_y;
    //printf("pannel (%d,%d)\n",readw(ADC_XDATA_ADD),readw(ADC_YDATA_ADD));
		
	if (COUNT == LEN-1)
	{
	   
	   X = 0;
	   for (i=0; i <= COUNT; i++)
	   {
	       X += AXIS_X[i];
	   }
	   X = X >> SHIFT;
	   
	   Y = 0;
	   for (i=0; i <= COUNT; i++)
	   {
	       Y += AXIS_Y[i];
	   }
	   Y = Y >> SHIFT;
	   COUNT = 0;
	   *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = 0x1f;
	   IsTouch = 1;
	   OUTPUT_X = X; 
	   OUTPUT_Y = Y;
	}
	
	//*(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = 0x1f;

	return 0;
}
#else
short ADCDataIn()
{
    printf("(%d %d)\n",readw(ADC_XDATA_ADD),readw(ADC_YDATA_ADD));
}

#endif

UINT8 volatile STATE;

void adc_irq()
{
	//UINT32 volatile i;
	ADC_CON_REG.value = readw(ADC_CON_ADD);
	
	if ( WT_INT==1 && STATE==0 )	
	{
		STATE = 1;
		COUNT = 0;
		//writew(ADC_TSC_ADD,readw(ADC_TSC_ADD) & 0xeff); // X position
		writew(ADC_TSC_ADD,0x0); // x position
		
		WT_INT = 0;
		ADC_INT_EN = 1;		
		WT_INT_EN = 0;
		ADC_TSC_MODE = 1;//semi-auto mode
		ADC_CONV = 1;
			
		writew(ADC_CON_ADD,ADC_CON_REG.value);
	
        //printf("state 0\n");
	}

	if (ADC_INT==1 && STATE==1)
	{		
		STATE = 2;
		//writew(ADC_TSC_ADD,readw(ADC_TSC_ADD)|0x100);// X position
		writew(ADC_TSC_ADD,0x100);// y position
		
		ADC_INT = 0;
		ADC_INT_EN = 1;		
		WT_INT_EN = 0;
		ADC_TSC_MODE = 1;//semi-auto mode
		ADC_CONV = 1;
		
		writew(ADC_CON_ADD,ADC_CON_REG.value);
        //printf("state 1\n");	
	
	}
	
	if(ADC_INT==1 && STATE==2)
	{
		ADCDataIn();
		COUNT++;
		ADC_INT = 0;
		ADC_INT_EN = 0;	
		WT_INT_EN = 0; // close WT interrupt.
		ADC_TSC_MODE = 3;//wt mode
		writew(ADC_CON_ADD,ADC_CON_REG.value);
		
		//STATE = 3;
	
		writew(REG_TICR0, 5000);//set time=0.3ms
		writew(REG_TCSR0, 0x60000000);//enable and one shot			
        //printf("state 2\n");		
	}
	return;
}

void timer0_irq()
{
	writew(REG_TISR, 0x1); //clear timer0 interrupt
	writew(REG_TCSR0, 0L); //disable timer0
	
    //printf("state 3\n");	
	if((readw(ADC_TSC_ADD)&0x1)==0x1) //down
	{
		writew(ADC_TSC_ADD,0x0); // x position
		ADC_TSC_MODE = 1;//semi-auto mode
		ADC_INT_EN = 1;		
		WT_INT_EN = 0;
		ADC_CONV = 1;
		writew(ADC_CON_ADD,ADC_CON_REG.value);
		STATE = 1;
		
	}
	else
	{
 	    ADC_INT_EN = 0;		
    	WT_INT_EN = 1;   		
			
	    ADC_TSC_MODE = 3;
			
	    WT_INT = 0;
		ADC_INT = 0;	
		writew(ADC_CON_ADD,ADC_CON_REG.value);  
		pre_x = pre_y = 0;
		STATE = 0;
	}	
	
	return;
}



INT diag_adc(void)
{  
    UINT32 *pframbuf=NULL;
    int	i;
	UINT32 tmp32;

 	/* enable the ADC clock */
	tmp32 = readw(CLKEN);
	tmp32 = tmp32 | 0x10000000;
  	writew(CLKEN,tmp32);

	/* enable the TIMER0 clock */
	tmp32 = readw(CLKEN);
	tmp32 = tmp32 | 0x00080000;
  	writew(CLKEN,tmp32);
	//printf("MFSEL=0x%x\n",readw(CLKEN));
 
    //while(1) printf("end\n");
 
/* ----------Video Initialization (Display_Continus)-----------------  */    

	pframbuf = vpostGetFrameBuffer();
	LCD_BUFF_BASE = (int) pframbuf;
    for (i=0;i<320*240;i++)
    {
  	    *pframbuf++ = 0;
    }	        
            
	
	sysSetInterruptType(IRQ_ADC, HIGH_LEVEL_SENSITIVE);
	sysInstallISR(IRQ_LEVEL_1, IRQ_ADC, (PVOID)adc_irq);
	sysSetLocalInterrupt(ENABLE_IRQ);                            
	sysEnableInterrupt(IRQ_ADC); 	

	sysSetInterruptType(IRQ_TIMER0, HIGH_LEVEL_SENSITIVE);
	sysInstallISR(IRQ_LEVEL_1, IRQ_TIMER0, (PVOID)timer0_irq);
	sysSetLocalInterrupt(ENABLE_IRQ);                            
	sysEnableInterrupt(IRQ_TIMER0); 		
	
	//writew(REG_TICR0,26500);//0x6784
	//writew(REG_TCR0,0x60000000);

	/* ADC clock */
	printf("ADC start \n");

	/* reset */
	ADC_CON_REG.value = 0L;
	ADC_RST = 1;
	writew(ADC_CON_ADD,ADC_CON_REG.value);
	ADC_CON_REG.value = 0L;	
	writew(ADC_CON_ADD,ADC_CON_REG.value);
	
	
	/* ADC setting */	
	/* set delay and screen type */
	ADC_TSC_TYPE = 0; //0:4wire 1:5wire 2:8wire
	writew(ADC_TSC_ADD,ADC_TSC_REG.value);
	
	
	//writew(ADC_DLY_ADD,150);	
    writew(ADC_DLY_ADD,0x10000);
	
	/* waitting for trigger mode */
	ADC_DIV = 4;
	WT_INT_EN = 1;
	//ADC_INT_EN = 1;
	ADC_EN = 1;
	ADC_TSC_MODE = 3;
	
	WT_INT = 0;
	ADC_INT = 0;	
	writew(ADC_CON_ADD,ADC_CON_REG.value);		
	
	STATE = 0;

	//*(short*)(LCD_BUFF_BASEADD+240*2) = 0x1f;
	pre_x = pre_y = 0;
    
    
    
    SetTarget( AXIS_X1, AXIS_Y1);
    
    printf("Please touch 1st target\n");
    IsTouch = 0;
    while(!IsTouch);    
    //printf("Target1 touch\n");
    if ( (OUTPUT_X > (AXIS_X1+20)) || (OUTPUT_X < (AXIS_X1-20)) || (OUTPUT_Y > (AXIS_Y1+20)) || (OUTPUT_Y < (AXIS_Y1-20)) )
    {
       printf("FAIL, OUT RANGE\n");
    }
    else
    {
       for(t=0;t<0x1000000;t++);
       //ResetScreen();
       
       SetTarget( AXIS_X2, AXIS_Y2);
       printf("Please touch 2nd target\n");    
       IsTouch = 0;
       while(!IsTouch);    
       //printf("Target2 touch\n");
         
       if ( (OUTPUT_X > (AXIS_X2+20)) || (OUTPUT_X < (AXIS_X2-20)) || (OUTPUT_Y > (AXIS_Y2+20)) || (OUTPUT_Y < (AXIS_Y2-20)) )
       {
          printf("FAIL, OUT RANGE\n");   
       }
       else    
       {
          for(t=0;t<0x1000000;t++);
          //ResetScreen();
          
          SetTarget( AXIS_X3, AXIS_Y3);
          printf("Please touch 3rd target\n");
          IsTouch = 0;
          while(!IsTouch);    
          //printf("Target3 touch\n");
       
          if ( (OUTPUT_X > (AXIS_X3+20)) || (OUTPUT_X < (AXIS_X3-20)) || (OUTPUT_Y > (AXIS_Y3+20)) || (OUTPUT_Y < (AXIS_Y3-20)) )
          {
             printf("FAIL, OUT RANGE\n");   ;
          }
          else    
          {          
             for(t=0;t<0x1000000;t++);    
             //ResetScreen();
             
             SetTarget( AXIS_X4,AXIS_Y4);    
             printf("Please touch 4th target\n");
             IsTouch = 0;
             while(!IsTouch);    
             //printf("Target4 touch\n");       
             
             if ( (OUTPUT_X > (AXIS_X4+20)) || (OUTPUT_X < (AXIS_X4-20)) || (OUTPUT_Y > (AXIS_Y4+20)) || (OUTPUT_Y < (AXIS_Y4-20)) )
             {
                printf("FAIL, OUT RANGE\n");   
             
             }
             else    
             {        
                printf("TEST OK\n");
             }  
             for(t=0;t<0x1000000;t++);
             ResetScreen();
          }  
       }
    }
    
    //while(1);
	
    return 0;
}



VOID SetTarget(INT16 Center_X, INT16 Center_Y)
{
    //Center_X = 60;
    //Center_Y = 60; 
    INT16 X,Y;

	Center_Y = 240 - Center_Y;

    for (X = (Center_X-20); X <= (Center_X+20); X++)
    {
       Y = Center_Y - 20;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
       Y = Center_Y + 20;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
    }
    
    for (Y = (Center_Y-20); Y <= (Center_Y+20); Y++)
    {
       X = Center_X - 20;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
       X = Center_X + 20;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
    }    
    
    for (X = (Center_X-20+1); X < (Center_X+20); X++)
    {
       for (Y = (Center_Y-20+1); Y < (Center_Y+20); Y++)
       {
           *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xFFFF;
       }
    }
    
    for (X = (Center_X-5); X <= (Center_X+5); X++)
    {
       Y = Center_Y;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
    }
    
    for (Y = (Center_Y-5); Y <= (Center_Y+5); Y++)
    {
       X = Center_X;
       *(short*)(LCD_BUFF_BASE+(Y*320+X)*2) = (short)0xF800;
    }    

}

VOID ResetScreen(VOID)
{
	short *ptr;
	int i;
	
	ptr = (short*)LCD_BUFF_BASE;

    for(i=0;i<320*240;i++)
    {
    	*ptr++ = 0;
    }
}

